package com.rgbgame.game;

import processing.core.PConstants;

/**
     * Handles recording and playing back of player's actions.
 */

class ActionRecorder {

    // NOTE: encapsulation of this class is broken by key interactions as
    // follows:
    // keyRight, keyLeft, keyState['r'/'g'/'b'], rePose (all boolean)
    // These are globals, but can't all be linked from the class because
    // freaking Java doesn't allow pointers to built-in types.

    private int[] rDownEvents;
    private int[] gDownEvents;
    private int[] bDownEvents;
    private int[] rightDownEvents;
    private int[] leftDownEvents;
    private int[] rUpEvents;
    private int[] gUpEvents;
    private int[] bUpEvents;
    private int[] rightUpEvents;
    private int[] leftUpEvents;

    private int rDownCount;
    private int gDownCount;
    private int bDownCount;
    private int rightDownCount;
    private int leftDownCount;
    private int rUpCount;
    private int gUpCount;
    private int bUpCount;
    private int rightUpCount;
    private int leftUpCount;

    private int rDownPlay;
    private int gDownPlay;
    private int bDownPlay;
    private int rightDownPlay;
    private int leftDownPlay;
    private int rUpPlay;
    private int gUpPlay;
    private int bUpPlay;
    private int rightUpPlay;
    private int leftUpPlay;

    public boolean dataLoaded;
    private rgbGame rgbGame;

    public ActionRecorder(rgbGame rgbGame) {
        this.rgbGame = rgbGame;
        reset();
    }

    public void reset() {
        resetRecorder();
        resetPlayer();
    }

    public void resetRecorder() {
        resetRecorder(30);
    }

    public void resetRecorder(int iNum) {
        rDownEvents = new int[iNum];
        gDownEvents = new int[iNum];
        bDownEvents = new int[iNum];
        rightDownEvents = new int[iNum];
        leftDownEvents = new int[iNum];
        rUpEvents = new int[iNum];
        gUpEvents = new int[iNum];
        bUpEvents = new int[iNum];
        rightUpEvents = new int[iNum];
        leftUpEvents = new int[iNum];

        for (int i = 0; i < iNum; i++) {
            rDownEvents[i] = -1;
            gDownEvents[i] = -1;
            bDownEvents[i] = -1;
            rightDownEvents[i] = -1;
            leftDownEvents[i] = -1;
            rUpEvents[i] = -1;
            gUpEvents[i] = -1;
            bUpEvents[i] = -1;
            rightUpEvents[i] = -1;
            leftUpEvents[i] = -1;
        }

        rDownCount = 0;
        gDownCount = 0;
        bDownCount = 0;
        rightDownCount = 0;
        leftDownCount = 0;

        rUpCount = 0;
        gUpCount = 0;
        bUpCount = 0;
        rightUpCount = 0;
        leftUpCount = 0;

        dataLoaded = false;
    }

    public void resetPlayer() {
        rDownPlay = 0;
        gDownPlay = 0;
        bDownPlay = 0;
        rightDownPlay = 0;
        leftDownPlay = 0;

        rUpPlay = 0;
        gUpPlay = 0;
        bUpPlay = 0;
        rightUpPlay = 0;
        leftUpPlay = 0;
    }

    public void cleanup(int sCount) {
        rightUpEvents[rightUpCount++] = sCount;
        leftUpEvents[leftUpCount++] = sCount;
        rUpEvents[rUpCount++] = sCount;
        gUpEvents[gUpCount++] = sCount;
        bUpEvents[bUpCount++] = sCount;
    }

    public void recordDownActions(int keyCode, int key, int sCount) {
        checkLengths(); // safety check so we don't run off end of array
        if (key == PConstants.CODED) {
            if (keyCode == PConstants.RIGHT) {
                rightDownEvents[rightDownCount] = sCount;
                rightDownCount++;
            } else if (keyCode == PConstants.LEFT) {
                leftDownEvents[leftDownCount] = sCount;
                leftDownCount++;
            }
        }

        if ((key == 'r' || key == 'R')) {
            rDownEvents[rDownCount] = sCount;
            rDownCount++;
        }

        if ((key == 'g' || key == 'G')) {
            gDownEvents[gDownCount] = sCount;
            gDownCount++;
        }

        if ((key == 'b' || key == 'B')) {
            bDownEvents[bDownCount] = sCount;
            bDownCount++;
        }
    }

    public void recordUpActions(int keyCode, int key, int sCount) {
        checkLengths();
        if (key == PConstants.CODED) {
            if (keyCode == PConstants.RIGHT) {
                rightUpEvents[rightUpCount] = sCount;
                rightUpCount++;
            } else if (keyCode == PConstants.LEFT) {
                leftUpEvents[leftUpCount] = sCount;
                leftUpCount++;
            }
        }

        if ((key == 'r' || key == 'R')) {
            rUpEvents[rUpCount] = sCount;
            rUpCount++;
        }

        if ((key == 'g' || key == 'G')) {
            gUpEvents[gUpCount] = sCount;
            gUpCount++;
        }
        if ((key == 'b' || key == 'B')) {
            bUpEvents[bUpCount] = sCount;
            bUpCount++;
        }
    }

    public void loadKeyStates(int sCount) { //
        // if (startWatch) println(sCount);

        while (sCount == rDownEvents[rDownPlay]) {
            // if (startWatch) println("rdown");
            if (!rgbGame.keyState['r']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['r'] = true;
            if (rDownPlay < rDownCount)
                rDownPlay++;
        }
        while (sCount == rUpEvents[rUpPlay]) {
            // if (startWatch) println("rup");
            if (rgbGame.keyState['r']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['r'] = false;
            if (rUpPlay < rUpCount)
                rUpPlay++;
            // println(stepCount);
        }
        while (sCount == gDownEvents[gDownPlay]) {
            if (!rgbGame.keyState['g']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['g'] = true;
            if (gDownPlay < gDownCount)
                gDownPlay++;
        }
        while (sCount == gUpEvents[gUpPlay]) {
            if (rgbGame.keyState['g']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['g'] = false;
            if (gUpPlay < gUpCount)
                gUpPlay++;
        }
        while (sCount == bDownEvents[bDownPlay]) {
            if (!rgbGame.keyState['b']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['b'] = true;
            if (bDownPlay < bDownCount)
                bDownPlay++;
        }
        while (sCount == bUpEvents[bUpPlay]) {
            if (rgbGame.keyState['b']) {
                rgbGame.rePose = true;
            }
            rgbGame.keyState['b'] = false;
            if (bUpPlay < bUpCount)
                bUpPlay++;
        }
        while (sCount == rightDownEvents[rightDownPlay]) {
            rgbGame.keyRight = true;
            if (rightDownPlay < rightDownCount)
                rightDownPlay++;
        }
        while (sCount == rightUpEvents[rightUpPlay]) {
            rgbGame.keyRight = false;
            if (rightUpPlay < rightUpCount)
                rightUpPlay++;
        }
        while (sCount == leftDownEvents[leftDownPlay]) {
            rgbGame.keyLeft = true;
            if (leftDownPlay < leftDownCount)
                leftDownPlay++;
        }
        while (sCount == leftUpEvents[leftUpPlay]) {
            rgbGame.keyLeft = false;
            if (leftUpPlay < leftUpCount)
                leftUpPlay++;
        }
    }

    private void checkLengths() {
        if (rDownCount > rDownEvents.length - 5)
            rDownEvents = growIntArray(rDownEvents);
        if (gDownCount > gDownEvents.length - 5)
            gDownEvents = growIntArray(gDownEvents);
        if (bDownCount > bDownEvents.length - 5)
            bDownEvents = growIntArray(bDownEvents);
        if (rUpCount > rUpEvents.length - 5)
            rUpEvents = growIntArray(rUpEvents);
        if (gUpCount > gUpEvents.length - 5)
            gUpEvents = growIntArray(gUpEvents);
        if (bUpCount > bUpEvents.length - 5)
            bUpEvents = growIntArray(bUpEvents);
        if (rightDownCount > rightDownEvents.length - 5)
            rightDownEvents = growIntArray(rightDownEvents);
        if (leftDownCount > leftDownEvents.length - 5)
            leftDownEvents = growIntArray(leftDownEvents);
        if (rightUpCount > rightUpEvents.length - 5)
            rightUpEvents = growIntArray(rightUpEvents);
        if (leftUpCount > leftUpEvents.length - 5)
            leftUpEvents = growIntArray(leftUpEvents);
    }

    private int[] growIntArray(int[] extMe) {
        // println("Got here: "+extMe.length);
        int eLength = extMe.length;
        int nLength = (int) (eLength * 1.1f + 10);
        // println(nLength);
        int[] buff = new int[nLength];
        for (int i = 0; i < eLength; i++) {
            buff[i] = extMe[i];
        }
        for (int i = eLength; i < nLength; i++) { // this might not be
            // necessary, but do it
            // anyways
            buff[i] = -1;
        }
        return buff;
    }

}
